#!/usr/bin/env python
# coding=utf-8
import json
import pathlib

import pandas as pd
from easydict import EasyDict
from gm.api import subscribe, order_target_percent, PositionSide_Long, OrderType_Market, get_trading_dates, run, \
    MODE_BACKTEST, ADJUST_PREV
from ruamel import yaml
from tqdm import tqdm

from quant import strategy

start_time = '2021-01-01 08:00:00'
end_time = '2022-01-01 08:00:00'


def init(context):
    days = get_trading_dates(exchange='SZSE',
                             start_date=start_time,
                             end_date=end_time)
    with pathlib.Path(__file__).parent.parent.joinpath('backtest.yml').open(
            mode='r') as f:
        docs = {doc['name']: doc for doc in yaml.safe_load_all(f)}
        bt = EasyDict(docs['grid_dfcf_1m'])
    context.order_book_id = 'SZSE.300059'
    subscribe(symbols=context.order_book_id, frequency=bt.frequency)
    for s in bt.strategies:
        if 'grid' in bt:
            grid = eval(bt.grid)
            if 'grid' in s.params:
                s.params.grid = grid
                s.params.order_book_id = bt.order_book_id
            context.strategy = getattr(strategy, s.strategy)(**s.params)
    context.tqdm = tqdm(total=len(days))
    context.signals = []


def on_bar(context, bars):
    bar = bars[0]
    data = {}
    for field in [
            'amount', 'bob', 'close', 'data', 'eob', 'frequency', 'high',
            'low', 'open', 'position', 'pre_close', 'volume'
    ]:
        data[field] = getattr(bar, field)
    signal = context.strategy.generate_signal(pd.DataFrame([data]),
                                              context.now).iloc[0]
    context.signals.append(signal)
    if signal.signal in [
            strategy.TradeOp.OPEN, strategy.TradeOp.CLOSE,
            strategy.TradeOp.BUY, strategy.TradeOp.SELL
    ]:
        order_target_percent(symbol=context.order_book_id,
                             percent=signal.position,
                             position_side=PositionSide_Long,
                             order_type=OrderType_Market)
    context.tqdm.update()


def on_backtest_finished(context, indicator):
    result = {
        '买入次数': indicator['open_count'],
        '卖出次数': indicator['close_count'],
        '盈利次数': indicator['win_count'],
        '亏损次数': indicator['lose_count'],
        '最大回撤': indicator['max_drawdown'],
        '收益率': '{0:.2%}'.format(indicator['pnl_ratio']),
        '年化收益率': '{0:.2%}'.format(indicator['pnl_ratio_annual']),
        '卡玛比率': indicator['calmar_ratio'],
        '夏普比率': indicator['sharp_ratio'],
        '胜率': '{0:.2%}'.format(indicator['win_ratio'])
    }
    with open('%s.json' % context.strategy.name, 'w', encoding='utf8') as f:
        json.dump(result, f, sort_keys=True, indent=4, ensure_ascii=False)
    df = pd.DataFrame(context.signals)
    df.to_csv('%s.csv' % context.strategy.name, index=False)


if __name__ == '__main__':
    '''
        strategy_id策略ID, 由系统生成
        filename文件名, 请与本文件名保持一致
        mode运行模式, 实时模式:MODE_LIVE回测模式:MODE_BACKTEST
        token绑定计算机的ID, 可在系统设置-密钥管理中生成
        backtest_start_time回测开始时间
        backtest_end_time回测结束时间
        backtest_adjust股票复权方式, 不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
        backtest_initial_cash回测初始资金
        backtest_commission_ratio回测佣金比例
        backtest_slippage_ratio回测滑点比例
        '''
    run(strategy_id='38f848f5-5e55-11ec-b2cd-2a16a8610fe9',
        filename='grid.py',
        mode=MODE_BACKTEST,
        token='567120cd2f9b2ce8ae3fbd7ee76ed06bf899b512',
        backtest_start_time=start_time,
        backtest_end_time=end_time,
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=10000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001,
        serv_addr='192.168.1.122:7001')
